package yueyong.salarymanagement.module.business.salary.controller;

import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import yueyong.salarymanagement.common.anno.NoValidPrivilege;
import yueyong.salarymanagement.common.constant.ResponseCodeConst;
import yueyong.salarymanagement.common.domain.ResponseDTO;
import yueyong.salarymanagement.constant.SwaggerTagConst;
import yueyong.salarymanagement.module.business.salary.domain.dto.SalarySendDTO;
import yueyong.salarymanagement.module.business.salary.domain.entity.EmployeeSalaryEntity;
import yueyong.salarymanagement.module.business.salary.domain.entity.UserEntity;
import yueyong.salarymanagement.module.business.salary.domain.vo.ItemData;
import yueyong.salarymanagement.module.business.salary.domain.vo.SalaryImportData;
import yueyong.salarymanagement.module.business.salary.domain.vo.SalarySendResultVO;
import yueyong.salarymanagement.module.business.salary.service.EmployeeSalaryService;
import yueyong.salarymanagement.module.business.salary.service.UserService;
import yueyong.salarymanagement.module.system.login.domain.RequestTokenBO;
import yueyong.salarymanagement.util.*;

import javax.validation.Valid;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Copyright: yueyong (c) 2022
 *
 * @author he.shaorong
 * @version 1.0
 * @date 2022/2/5
 */
@RestController
@Api(tags = {SwaggerTagConst.Admin.BUSINESS})
public class SalaryRecordsController {

    private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);


    @Autowired
    private EmployeeSalaryService employeeSalaryService;

    @Autowired
    private UserService userService;

    @ApiOperation(value = "新建工资条 - 预览发送 - 点击发送 - 薪资发放接口", notes = "设置薪资发放信息，发放不同类型信息到不同平台")
    @PostMapping("/user/sendSetting")
    @NoValidPrivilege
    public ResponseDTO sendSetting(@Valid @RequestBody SalarySendDTO salarySendDTO) {
        RequestTokenBO requestToken = SmartRequestTokenUtil.getRequestUser();
        Long uid = requestToken.getRequestUserId();
        List<EmployeeSalaryEntity> salaryEntityList = employeeSalaryService.getInitEmployeeSalaryEntityBySalaryId(uid, salarySendDTO.getSalaryId());
        if (salaryEntityList == null || salaryEntityList.size() == 0) {
            return ResponseDTO.wrap(ResponseCodeConst.NOT_EXISTS);
        }

        //记录一共发放几种消息用，临时方案，后面改动
        addSendTypeRecord(salaryEntityList.get(0), salarySendDTO);

        for (EmployeeSalaryEntity entity : salaryEntityList) {
            fixedThreadPool.execute(new Runnable() {
                public void run() {
                    try {
                        handleSendSalaryTask(entity, salarySendDTO, false);
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        //启用多线程
//        for (EmployeeSalaryEntity entity : salaryEntityList) {
//            handleSendSalaryTask(entity, salarySendDTO);
//        }

        return ResponseDTO.succ();
    }

    @GetMapping("/user/getSendSalarySlipResult")
    @ApiOperation(value = "新建工资条 - 发送结果 - 查询薪资发放接口结果", notes = "返回发放结果，n个成功，n个失败")
    @NoValidPrivilege
    public ResponseDTO<SalarySendResultVO> getSendSalarySlipResult(@RequestParam long salaryId) {
        RequestTokenBO requestToken = SmartRequestTokenUtil.getRequestUser();
        Long uid = requestToken.getRequestUserId();
        List<EmployeeSalaryEntity> salaryEntityList = employeeSalaryService.getEmployeeSalaryEntityBySalaryId(uid, salaryId);
        if (salaryEntityList == null || salaryEntityList.size() == 0) {
            return ResponseDTO.wrap(ResponseCodeConst.NOT_EXISTS);
        }

        int successCount = (int) salaryEntityList.stream().filter(salary -> salary.getState() == 0).count();
        int failedCount = (int) salaryEntityList.stream().filter(salary -> salary.getState() == 1).count();

        long sentTypeCount = getSentTypeCount(salaryEntityList);

        List<EmployeeSalaryEntity> salaryEntityInitList = employeeSalaryService.getInitEmployeeSalaryEntityBySalaryId(uid, salaryId);
        long allCount = sentTypeCount * salaryEntityInitList.size();
        long finishedSize = successCount + failedCount;
        boolean isFinished = finishedSize >= allCount;

        SalarySendResultVO salarySendResultVO = new SalarySendResultVO();
        salarySendResultVO.setSuccessCount(successCount);
        salarySendResultVO.setFailedCount(failedCount);
        salarySendResultVO.setFinished(isFinished);
        salarySendResultVO.setTotalCount((int)allCount);

        return ResponseDTO.succData(salarySendResultVO);
    }

    private long getSentTypeCount(List<EmployeeSalaryEntity> salaryEntityList) {
        EmployeeSalaryEntity sendTypeEntity = salaryEntityList.stream().filter(item -> item.getState() == -10).findFirst().orElse(null);

        if(Objects.nonNull(sendTypeEntity)) {
            return Long.valueOf(sendTypeEntity.getStateReason());
        }

        long sentTypeCount = salaryEntityList.stream().filter(item -> item.getSendType() > 0).map(item -> item.getSendType()).distinct().count();
        if(sentTypeCount >0) {
            return sentTypeCount;
        }

        return sentTypeCount;

    }

    public boolean handleSendSalaryTask(EmployeeSalaryEntity entity, SalarySendDTO salarySendDTO, boolean resend) {
        //还原出dataItem
        JSONObject jsonObject = JSONObject.parseObject(entity.getSalaryItems());
        SalaryImportData salaryImportData = JSONObject.toJavaObject(jsonObject, SalaryImportData.class);


        //发送各种信息，记录发送结果
        ItemData salaryItem = salaryImportData.getSalaryData().stream().filter(itemData -> itemData.getItemName()
                .equalsIgnoreCase("实发工资")).findFirst().orElse(null);
        String salaryStr = salaryItem == null ? "" : salaryItem.getItemValue();


        ItemData emailItem = salaryImportData.getSalaryData().stream().filter(itemData -> itemData.getItemName()
                .equalsIgnoreCase("邮箱")).findFirst().orElse(null);
        String emailStr = emailItem == null ? "" : emailItem.getItemValue();

        ItemData shortMessageItem = salaryImportData.getSalaryData().stream().filter(itemData -> itemData.getItemName()
                .equalsIgnoreCase("手机号")).findFirst().orElse(null);
        String shortMessageStr = shortMessageItem == null ? "" : shortMessageItem.getItemValue();

        boolean result = false;
        boolean sendedWx = false;
        //邮件
        if (salarySendDTO.isEmailMessage() && Strings.isNotBlank(emailStr)) {
            result = sendEmail(emailStr, salaryStr, salarySendDTO, salaryImportData, entity, resend);
        }
        //短信
        if (salarySendDTO.isShortMessage() && Strings.isNotBlank(shortMessageStr)) {
            result = sendShortMeassage(salarySendDTO, entity, resend);
            sendedWx = senWxMessage(salarySendDTO, entity, resend);
            result = sendedWx;
        }
        //微信公众号
        if (salarySendDTO.isSendWeChat() && !sendedWx) {
            result = senWxMessage(salarySendDTO, entity, resend);
        }
        //企业微信, 待开发
        if (salarySendDTO.isSendEntWeChat()) {
            result = sendEnvWxMessage(salarySendDTO, entity, resend);

        }

        return result;
    }

    private boolean sendEmail(String addrsss, String salaryStr, SalarySendDTO salarySendDTO
            , SalaryImportData salaryImportData, EmployeeSalaryEntity entity, boolean resend) {
        Timestamp sendTime = new Timestamp(salarySendDTO.getPayDate());
        Date sendDate = sendTime;

        String htmlContent = SendEmailUtil.buildHtmlContent(salarySendDTO.getCompanyName(), sendDate, salaryImportData, salaryStr);

//        boolean result = SendEmailUtil.sendEmail(htmlContent, addrsss);
        Pair<Boolean, String> resultPair = SendEmailUtilV2.sendEmail(htmlContent, addrsss);
        entity.setPayDate(new Timestamp(salarySendDTO.getPayDate()));
        entity.setSendType(2);
        if (resultPair.getKey()) {
            entity.setState(0);
            entity.setStateReason(resultPair.getValue());
        } else {
            entity.setState(1);
            entity.setStateReason(resultPair.getValue());
        }
        entity.setMsgSendTime(Timestamp.from(Instant.now()));
        if(resend) {
            employeeSalaryService.updateEmployeeSalaryEntity(entity);
        } else {
            entity.setId(null);
            employeeSalaryService.addEmployeeSalaryEntity(entity);
        }
        return resultPair.getKey();
    }

    private boolean sendShortMeassage(SalarySendDTO salarySendDTO, EmployeeSalaryEntity entity, boolean resend) {

        Timestamp payTime = new Timestamp(salarySendDTO.getPayDate());
        Date payDate = payTime;

        String name = entity.getEmployeeName();
        String mobilePhone = String.valueOf(entity.getMobilePhone());
        String companyName = salarySendDTO.getCompanyName();

        String content = SendShortMessageUtil.buildShortMessageContent(companyName, null, name, payDate);
        Pair<Boolean, String> resultPair = SendShortMessageUtil.sendShortMessage(content, mobilePhone);

        entity.setPayDate(new Timestamp(salarySendDTO.getPayDate()));
        entity.setSendType(4);

        if (resultPair.getKey()) {
            entity.setState(0);
            entity.setStateReason("ok");
        } else {
            entity.setState(1);
            entity.setStateReason(resultPair.getValue());
        }
        entity.setMsgSendTime(Timestamp.from(Instant.now()));
        if(resend) {
            employeeSalaryService.updateEmployeeSalaryEntity(entity);
        } else {
            entity.setId(null);
            employeeSalaryService.addEmployeeSalaryEntity(entity);
        }
        return resultPair.getKey();
    }

    private boolean senWxMessage(SalarySendDTO salarySendDTO, EmployeeSalaryEntity entity, boolean resend) {

        Pair<Boolean, String> result = Pair.of(false, "sendWxInit");
        Timestamp payTime = new Timestamp(salarySendDTO.getPayDate());
        LocalDate date = payTime.toLocalDateTime().toLocalDate();
        String name = entity.getEmployeeName();
        String mobilePhone = String.valueOf(entity.getMobilePhone());
        String companyName = salarySendDTO.getCompanyName();
        String job = "xx岗位";

        String openId = getOpenIdFromUserTable(mobilePhone);
        if(Objects.nonNull(openId)) {
            result = SendWxMessageUtil.sendMessage(name, companyName, date, job, openId);
        }

        entity.setPayDate(new Timestamp(salarySendDTO.getPayDate()));
        entity.setSendType(1);
        if (result.getKey()) {
            entity.setState(0);
            entity.setStateReason(result.getValue());
        } else {
            entity.setState(1);
            entity.setStateReason(result.getValue());
        }

        entity.setMsgSendTime(Timestamp.from(Instant.now()));
        if(resend) {
            employeeSalaryService.updateEmployeeSalaryEntity(entity);
        } else {
            entity.setId(null);
            employeeSalaryService.addEmployeeSalaryEntity(entity);
        }
        return result.getKey();
    }

    private boolean sendEnvWxMessage(SalarySendDTO salarySendDTO, EmployeeSalaryEntity entity, boolean resend) {
        entity.setPayDate(new Timestamp(salarySendDTO.getPayDate()));
        entity.setSendType(3);
        entity.setState(1);
        entity.setStateReason("暂不支持");

        entity.setMsgSendTime(Timestamp.from(Instant.now()));
        if(resend) {
            employeeSalaryService.updateEmployeeSalaryEntity(entity);
        } else {
            entity.setId(null);
            employeeSalaryService.addEmployeeSalaryEntity(entity);
        }
        return false;
    }


    private String getOpenIdFromUserTable(String phone) {
        List<UserEntity> results = userService.getUserEntityFromPhoneNumber(phone);
        if(results != null && results.size() >0) {
            return results.get(0).getOpenid();
        }
        return null;
    }

    private void addSendTypeRecord(EmployeeSalaryEntity entity, SalarySendDTO dto) {
        int typeCount = 0;
        if(dto.isSendWeChat()) {
            typeCount +=1;
        }
        if(dto.isSendEntWeChat()) {
            typeCount +=1;
        }
        if(dto.isShortMessage()) {
            typeCount +=1;
        }
        if(dto.isEmailMessage()) {
            typeCount +=1;
        }
        entity.setStateReason(String.valueOf(typeCount));
        entity.setState(-10);
        employeeSalaryService.addEmployeeSalaryEntity(entity);
    }
}
